#include "BaseObject.h"
#include "CEvent.h"
#include "Camera.h"
#include "../wrappers/CSGD_Direct3D.h"
#include "../wrappers/CSGD_EventSystem.h"


#include <assert.h>


CBaseObject::CBaseObject(void)
{
	SetPosition( 10.0, 0.0, 10.0 );
	SetRelativePosition( GetPosition() );

	m_unHeight		= 100;
	m_unWidth		= 50;
	m_unRefCount	= 1;
	m_bIsGrounded	= true;

	CSGD_EventSystem::GetInstance()->RegisterClient( "grounded", this );
}


CBaseObject::~CBaseObject(void)
{
	CSGD_EventSystem::GetInstance()->UnregisterClientAll(this);
}

void CBaseObject::Update( float fElapsedTime )
{	
	if( m_bIsGrounded == false )
	{
		m_tPosition.fY += GRAVITY * fElapsedTime;
		m_tRelativePosition.fY += GRAVITY * fElapsedTime;
	}
	CCamera::GetInstance()->UpdateCameraPosition( this );
}

void CBaseObject::Render( void )
{
	
}

void CBaseObject::AddRef( void )
{
	m_unRefCount++;
}

void CBaseObject::Release( void )
{
	m_unRefCount--;

	if( m_unRefCount == 0 )
		delete this;
}


void CBaseObject::SetPosition( float fX, float fY, float fZ )
{
	m_tPosition.fX = fX;
	m_tPosition.fY = fY;
	m_tPosition.fZ = fZ;
}


void CBaseObject::SetRelativePosition( float fX, float fY, float fZ )
{
	m_tRelativePosition.fX = fX;
	m_tRelativePosition.fY = fY;
	m_tRelativePosition.fZ = fZ;
}


bool CBaseObject::CheckCollision( IObject* pOther )
{
	RECT rOverlap;

	if( IntersectRect( &rOverlap, &GetBaseRect(), &pOther->GetBaseRect() ) == true ) 
	{
		float fHalfWidth = (float)m_unWidth/2;
		float fHalfHeight= (float)m_unHeight/2;

		CBaseObject* pObject = dynamic_cast< CBaseObject* >( pOther );
		assert( pObject != nullptr && "CBaseObject::CheckCollision - pOther cannot convert to CBaseObject*" );

		if( IsGrounded() != pObject->IsGrounded() )
		{
			if( m_bIsGrounded == false && ((float)m_unHeight/2 + m_tPosition.fY >= 
				pObject->m_tPosition.fY - (float)pObject->m_unHeight/2) == false )
				return false;
			else if( m_bIsGrounded == true && ((float)pObject->m_unHeight/2 + pObject->m_tPosition.fY >= 
				m_tPosition.fY - (float)m_unHeight/2) == false  )
				return false;
		}
		else return true;
		//else
		//{
		//	float distance = pObject->GetPosition().fZ - GetPosition().fZ;
		//	if( distance < 0.0f ) distance *= -1;
		//
		//	if( distance > (float)(GetWidth()/3) )
		//		return false;
		//
		//}
	}
	else
	{
		return false;
	}	
}

void CBaseObject::HandleEvent( CEvent* pEvent )
{
	if( pEvent->GetEventID() == "grounded" &&
		pEvent->GetParam() == this )
	{
		m_bIsGrounded == true;
	}
}

RECT CBaseObject::GetBaseRect( void )
{
	/*
	return AnimationsManager::GetInstance()->GetBaseRect( m_tAnimInfo );
	*/
	RECT rBase;
	if( m_bIsGrounded == true )
	{
		rBase = GetRect();
		rBase.top = rBase.bottom - (LONG)m_unWidth;
	}
	else
	{
		rBase.left = LONG(m_tRelativePosition.fX - m_unWidth/2);
		rBase.right= LONG(m_tRelativePosition.fX + m_unWidth/2);
		rBase.bottom = LONG(m_tRelativePosition.fZ + m_unHeight/2);
		rBase.top  = rBase.bottom - LONG(m_unWidth);
	}
	return rBase;
}

RECT CBaseObject::GetRect( void )
{
	RECT rSelf;
	float fY = m_tRelativePosition.fZ - 0.3f * m_tRelativePosition.fY;
	rSelf.left = LONG(m_tRelativePosition.fX -= m_unWidth/2);
	rSelf.right= LONG(m_tRelativePosition.fX += m_unWidth/2);
	rSelf.top  = LONG(fY -= m_unHeight/2);
	rSelf.bottom = LONG(fY +=m_unHeight/2);
	return rSelf;
}
